package com.sojson.util.pay.wx.bean;

import java.util.TreeMap;

import com.ijpay.core.kit.PayKit;
import com.ijpay.core.kit.WxPayKit;
import com.sojson.config.exception.bean.Status;
import com.sojson.util.StringUtil;
import com.sojson.util.SystemParamBaseUtil;
import com.sojson.util.pay.bean.PayResult;
import com.sojson.util.pay.wx.WxUtil;
import com.sojson.util.pay.wx.constant.WxConstant;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * 返回给前端的微信接口参数Bean
 *
 * @author liu
 * @date 2021-03-16
 */
@Data
@ApiModel("微信接口返回信息")
public class WxResult extends PayResult {

    /***/
    private static final long serialVersionUID = 2231406852564862492L;

    /** appid类似帐号 */
    @ApiModelProperty("appid类似帐号")
    private String appid;
    /** 企业微信应用ID */
    @ApiModelProperty("企业微信应用ID")
    private String agentid;
    /** 网页授权接口调用凭证,注意：此access_token与基础支持的access_token不同 */
    @ApiModelProperty("网页授权接口调用凭证,注意：此access_token与基础支持的access_token不同")
    private String accessToken;
    /** 用户唯一标识，请注意，在未关注公众号时，用户访问公众号的网页，也会产生一个用户和公众号唯一的OpenID */
    @ApiModelProperty("用户唯一标识，请注意，在未关注公众号时，用户访问公众号的网页，也会产生一个用户和公众号唯一的OpenID")
    private String openid;
    /** 用户在开放平台的唯一标识符 */
    @ApiModelProperty("用户在开放平台的唯一标识符")
    private String unionid;
    /** 商户号 */
    @ApiModelProperty("商户号")
    private String mchid;
    /** 会话密钥 */
    @ApiModelProperty("会话密钥")
    private String sessionKey;
    /** 二维码链接 */
    @ApiModelProperty("二维码链接")
    private String codeUrl;
    /** 支付跳转链接 */
    @ApiModelProperty("支付跳转链接")
    private String wapUrl;
    /** 预支付交易会话ID */
    @ApiModelProperty("预支付交易会话ID")
    private String prepayid;
    /** 订单详情扩展字符串 */
    @ApiModelProperty("订单详情扩展字符串")
    private String descPackage;
    /** 时间戳 */
    @ApiModelProperty("时间戳")
    private long timestamp;
    /** 生成密钥的随机字符串 */
    @ApiModelProperty("生成密钥的随机字符串")
    private String nonceStr;
    /** 页面路径 */
    @ApiModelProperty("页面路径")
    private String url;
    /** 签名类型 */
    @ApiModelProperty("签名类型")
    private String signType;
    /** 签名 */
    @ApiModelProperty("签名")
    private String sign;
    /** jsapiTicket */
    @ApiModelProperty("jsapiTicket")
    private String jsapiTicket;
    /** 状态信息 */
    @ApiModelProperty("状态信息")
    private Status status;

    public WxResult() {}

    /**
     * 成功返回
     * @param code
     */
    public WxResult(Integer code) {
        this(code, null);
    }

    /**
     * 返回失败
     * @param code
     * @param msg
     */
    public WxResult(Integer code, String msg) {
        this(new Status(code, msg));
    }

    public WxResult(Status status) {
        this.status = status;
    }

    public WxResult(String accessToken, String openid) {
        this.accessToken = accessToken;
        this.openid = openid;
    }

    /**
     * 初始化签名内容
     * @throws Exception
     */
    public void initSign(String prepayId) throws Exception {
        String buildSignMessage = PayKit.buildSignMessage(getAppid(), getTimestamp(), getNonceStr(), prepayId);
        setSign(PayKit.createSign(buildSignMessage, SystemParamBaseUtil.getStr(WxConstant.CA_CERT_CACHE_KEY_PEM_KEY)));
    }

    /**
     * 初始化签名内容(V2接口)
     *
     * @param mchKey    商户密钥
     * @param prepayId  预支付会话标识
     * @throws Exception
     */
    public void initSignV2(String mchKey, String prepayId) throws Exception {
        WxParamV2<String> wxParam = new WxParamV2<>();
        wxParam.setAppid(getAppid());
        wxParam.setPartnerid(getMchid());
        wxParam.setPrepayid(prepayId);
        wxParam.setPackage(getDescPackage());
        wxParam.setNoncestr(getNonceStr());
        wxParam.setTimestamp(getTimestamp() + "");
        setSign(WxUtil.getPaySignObject(new TreeMap<>(wxParam.getMap()), mchKey));
    }

    /**
     * 初始化Native调起支付内容
     *
     * @param wxResponseV3
     */
    public void initNative(WxResponseV3 wxResponseV3) {
        initNative(wxResponseV3.getCodeUrl());
    }

    /**
     * 初始化Native调起支付内容(V2接口)
     *
     * @param wxResponseV2
     */
    public void initNativeV2(WxResponseV2 wxResponseV2) {
        initNative(wxResponseV2.getCodeUrl());
    }

    /**
     * 初始化Native调起支付内容
     *
     * @param codeUrl  二维码内容
     */
    public void initNative(String codeUrl) {
        setCodeUrl(codeUrl);
    }

    /**
     * 初始化App调起支付内容
     *
     * @param wxResponseV3
     * @throws Exception
     */
    public void initApp(WxResponseV3 wxResponseV3) throws Exception {
        initApp(wxResponseV3, wxResponseV3.getAppid(), wxResponseV3.getMchid());
    }

    /**
     * 初始化App调起支付内容
     *
     * @param wxResponseV3
     * @param appid     Appid
     * @param mchid     商户号
     * @throws Exception
     */
    public void initApp(WxResponseV3 wxResponseV3, String appid, String mchid) throws Exception {
        initApp(appid, mchid, wxResponseV3.getPrepayId());
    }

    /**
     * 初始化App调起支付内容
     *
     * @param appid     Appid
     * @param mchid     商户号
     * @param prepayId  预支付会话标识
     * @throws Exception
     */
    public void initApp(String appid, String mchid, String prepayId) throws Exception {
        setAppid(appid);
        setMchid(mchid);
        setPrepayid(prepayId);
        setDescPackage(WxConstant.PACKAGE_SING_WXPAY);
        setNonceStr(WxPayKit.generateStr());
        setTimestamp(System.currentTimeMillis() / 1000);
        initSign(getPrepayid());
    }

    /**
     * 初始化App调起支付内容(V2接口)
     *
     * @param wxResponseV2
     * @throws Exception
     */
    public void initAppV2(WxResponseV2 wxResponseV2) throws Exception {
        String appid = wxResponseV2.getMchAppid();
        initAppV2(wxResponseV2, StringUtil.isNotBlankObject(appid) ? appid : wxResponseV2.getAppid(),
            wxResponseV2.getMchid(), wxResponseV2.getMchKey());
    }

    /**
     * 初始化App调起支付内容(V2接口)
     *
     * @param wxResponseV2
     * @param appid     Appid
     * @param mchid     商户号
     * @param mchKey    商户密钥
     * @throws Exception
     */
    public void initAppV2(WxResponseV2 wxResponseV2, String appid, String mchid, String mchKey) throws Exception {
        initAppV2(appid, mchid, mchKey, wxResponseV2.getPrepayId());
    }

    /**
     * 初始化App调起支付内容(V2接口)
     *
     * @param appid     Appid
     * @param mchid     商户号
     * @param mchKey    商户密钥
     * @param prepayId  预支付会话标识
     * @throws Exception
     */
    public void initAppV2(String appid, String mchid, String mchKey, String prepayId) throws Exception {
        setAppid(appid);
        setMchid(mchid);
        setPrepayid(prepayId);
        setDescPackage(WxConstant.PACKAGE_SING_WXPAY);
        setNonceStr(WxPayKit.generateStr());
        setTimestamp(System.currentTimeMillis() / 1000);
        initSignV2(mchKey, getPrepayid());
    }

    /**
     * 初始化小程序调起支付内容
     *
     * @param wxResponseV3
     * @throws Exception
     */
    public void initXcx(WxResponseV3 wxResponseV3) throws Exception {
        initXcx(wxResponseV3, wxResponseV3.getAppid());
    }

    /**
     * 初始化小程序调起支付内容
     *
     * @param wxResponseV3
     * @param appid         Appid
     * @throws Exception
     */
    public void initXcx(WxResponseV3 wxResponseV3, String appid) throws Exception {
        initXcx(wxResponseV3.getAppid(), wxResponseV3.getPrepayId());
    }

    /**
     * 初始化小程序调起支付内容
     *
     * @param appid     Appid
     * @param prepayId  预支付会话标识
     * @throws Exception
     */
    public void initXcx(String appid, String prepayId) throws Exception {
        setAppid(appid);
        setTimestamp(System.currentTimeMillis() / 1000);
        setNonceStr(WxPayKit.generateStr());
        setDescPackage(String.format(WxConstant.PACKAGE_PERPAY_ID, prepayId));
        setSignType(WxConstant.SING_TYPE_RSA);
        initSign(getDescPackage());
    }

    /**
     * 初始化JSAPI调起支付内容
     *
     * @param wxResponseV3
     * @throws Exception
     */
    public void initJsapi(WxResponseV3 wxResponseV3) throws Exception {
        initJsapi(wxResponseV3, wxResponseV3.getAppid());
    }

    /**
     * 初始化JSAPI调起支付内容
     *
     * @param wxResponseV3
     * @param appid         Appid
     * @throws Exception
     */
    public void initJsapi(WxResponseV3 wxResponseV3, String appid) throws Exception {
        initJsapi(appid, wxResponseV3.getPrepayId());
    }

    /**
     * 初始化JSAPI调起支付内容
     *
     * @param appid     Appid
     * @param prepayId  预支付会话标识
     * @throws Exception
     */
    public void initJsapi(String appid, String prepayId) throws Exception {
        setAppid(appid);
        setTimestamp(System.currentTimeMillis() / 1000);
        setNonceStr(WxPayKit.generateStr());
        setDescPackage(String.format(WxConstant.PACKAGE_PERPAY_ID, prepayId));
        setSignType(WxConstant.SING_TYPE_RSA);
        initSign(getDescPackage());
    }

    /**
     * 初始化Wap调起支付内容
     *
     * @param wxResponseV3
     * @throws Exception
     */
    public void initWap(WxResponseV3 wxResponseV3) throws Exception {
        initWap(wxResponseV3.getWapUrl());
    }

    /**
     * 初始化Wap调起支付内容
     *
     * @param wapUrl    支付跳转链接
     * @throws Exception
     */
    public void initWap(String wapUrl) throws Exception {
        setWapUrl(wapUrl);
    }

}